package ru.spb.nicetu.altx.mnemo.extpoint.valuetypes;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.action.IAction;
import org.eclipse.swt.widgets.Composite;

/**
 * Базовый класс Composite-ов для отображения значений ITemplateValueType.
 */

@SuppressWarnings("unchecked")
public abstract class AValueTypeComposite extends Composite implements
    ICommandable {
  // **************************************************************************//
  // Enums //
  // **************************************************************************//

  // **************************************************************************//
  // Members //
  // **************************************************************************//

  // **************************************************************************//
  // Constructors //
  // **************************************************************************//

  public AValueTypeComposite(Composite parent, int style) {
    super(parent, style);
  }

  // **************************************************************************//
  // Getters //
  // **************************************************************************//

  // **************************************************************************//
  // Setters //
  // **************************************************************************//

  // **************************************************************************//
  // Publics //
  // **************************************************************************//

  public void addValueModifyListener(IValueModifyListener listener) {
    valueModifyListeners.add(listener);
  }

  public void removeValueModifyListener(IValueModifyListener listener) {
    valueModifyListeners.remove(listener);
  }
  
  public void addAppendedToSaveListener(IAppendedToSaveListener listener) {
    appendedToSaveListeners.add(listener);
  }

  public void removeAppendedToSaveListener(IAppendedToSaveListener listener) {
    appendedToSaveListeners.remove(listener);
  }

  public void addEditorRenameListener(IEditorRenameListener listener) {
    editorListeners.add(listener);
  }

  public void removeEditorRenameListener(IEditorRenameListener listener) {
    editorListeners.remove(listener);
  }
  
  
  public void setDirtyState(boolean dirty) {
    boolean oldDirty = this.dirty;
    this.dirty = dirty;
    // Было чисто, стало грязно
    if ((oldDirty == false) && (dirty == true)) {
      notifyValueModifyListeners();
    }
    // Было грязно, стало чисто
    if ((oldDirty == true) && (dirty == false)){
      notifyValueModifyListeners();
    }
  }

  public boolean isDirty() {
    return dirty;
  }

  public void appendValue(ITemplateValueType newValue, String newValueName) {
  }
  
  public void appendValue(ITemplateValueType newValue, String newValueName, IProject prj) {
  }
  
  /**
   * Должен вернуть актуальный заголовок редактора. 
   * Нужно для композыйтов с возможностью редактирования нескольких значений.
   */
  public String getEditorName() {
    return "";
  }
  
  /**
   * Переопределить метод, если необходимо возвращать список всех измененных 
   * дополнительных данных
   * @return - карта имя_значения-само_значение
   */
  public Map<String, ITemplateValueType> getChangedAppendedValues(){
    return new HashMap<String, ITemplateValueType>();
  }
  
  /**
   * Переопределить метод, если необходимо возвращать одно 
   * дополнительное значение редактора для того, чтобы сохранить это значение
   * отдельно от остальных
   * @return - карта имя_значения-само_значение
   */
  public HashMap<String, ITemplateValueType> getAppendedValueToSave() {
    return new HashMap<String, ITemplateValueType>();
  }
  
  @Deprecated
  public void setProject(IProject prj) {
  }

  // **************************************************************************//
  // Abstracts //
  // **************************************************************************//

  abstract public void setValue(ITemplateValueType value, String valueName);

  public void setValue(ITemplateValueType value) {
    setValue(value, null);
  };

  abstract public ITemplateValueType getValue();
  
  abstract public AValueTypeComposite createComposite(Composite parent,
                                                      int style);

  abstract public void doCommand(String id, IAction action);

  // **************************************************************************//
  // Protected //
  // **************************************************************************//

  protected void notifyValueModifyListeners() {
    for (Object l : valueModifyListeners.getListeners()) {
      IValueModifyListener listener = (IValueModifyListener) l;
      listener.modifyValue();
    }
  }
  
  protected void notifyAppendedToSaveListeners() {
    for (Object l : appendedToSaveListeners.getListeners()) {
      IAppendedToSaveListener listener = (IAppendedToSaveListener) l;
      listener.saveValue();
    }
  }
  
  public void notifyEditorRenameListeners() {
    for (Object l : editorListeners.getListeners()) {
      IEditorRenameListener listener = (IEditorRenameListener) l;
      listener.rename();
    }
  }

  // **************************************************************************//
  // Privates //
  // **************************************************************************//

  private boolean dirty;
  private ListenerList valueModifyListeners = new ListenerList();
  private ListenerList appendedToSaveListeners = new ListenerList();
  private ListenerList editorListeners = new ListenerList();
  // **************************************************************************//
  // Public Statics //
  // **************************************************************************//

  // **************************************************************************//
  // Private Statics //
  // **************************************************************************//

  // **************************************************************************//
  // Internal Classes //
  // **************************************************************************//

}
